package com.llxz.blog.article.service.impl;

import com.llxz.blog.article.dto.*;
import com.llxz.blog.article.entity.*;
import com.llxz.blog.article.repository.ArticleRepository;
import com.llxz.blog.article.repository.LabelRepository;
import com.llxz.blog.article.service.ArticleService;
import com.llxz.blog.article.util.DateUtil;
import com.llxz.blog.article.util.JsonResult;
import com.llxz.blog.article.util.TimeStamp;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 *
 * @author zzh && lyq
 * @description:. date: 2021/9/7 15:41
 */

@Service
@EnableMongoRepositories
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private LabelRepository labelRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void addOneArticle(Article article) {
        articleRepository.save(article);
    }

    @Override
    public void deleteArticle(Article article) {
        Query query = Query.query(Criteria.where("articleId").is(article.getArticleId()));
        System.out.println(query+"query========");
//        System.out.println(article+"artcle");
//        Article temp = articleRepository.findByArticleId(article.getArticleId());
////        for (String lbs : temp.getLabels()) {
////            Label res = labelRepository.getByLabel(lbs);
////            Query query1 = Query.query(Criteria.where("label").is(lbs));
////            Update update = Update.update("count", res.getCount() - 1);
////            mongoTemplate.updateFirst(query1, update, Label.class, "label");
////        }
        mongoTemplate.remove(query, Article.class, "article");
    }

    @Override
    public void updateArticle(Article article) {
        String articleId = article.getArticleId();
        article.setFlag(0);
        article.setDate(new Date());
        System.out.println(article+  "=======:article");
        Query query = Query.query(Criteria.where("articleId").is(article.getArticleId()));
        List<Article> list =  mongoTemplate.find(query, Article.class, "article");
        System.out.println("list:" +list);
        Article art =list.get(0);
        System.out.println("查询到的art："+art);
        article.setComments(art.getComments());
        article.setLikes(art.getLikes());
        article.setVisit(art.getVisit());
        this.deleteArticle(article);
        System.out.println(article+  "-------:article");
        articleRepository.save(article);
    }

    @Override
    public List<Article> getAllArticleByDate() {
        Query query = Query.query(Criteria.where("flag").is(1)).with(Sort.by(Sort.Direction.DESC, "date"));
        List<Article> list = mongoTemplate.find(query, Article.class, "article");
        return list;
    }

    @Override
    public void CheckAndPass(String articleId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("articleId").is(articleId));
        Update update = Update.update("flag", 1);
        mongoTemplate.updateFirst(query, update, Article.class, "article");
        List<String> labels = articleRepository.findByArticleId(articleId).getLabels();
        if (labels == null || labels.size() == 0) {
            return;
        }
        for (String label : labels) {
            Label res = labelRepository.getByLabel(label);
            if (res == null) {
                Label temp = new Label();
                temp.setLabel(label);
                temp.setCount(1);
                labelRepository.save(temp);
            } else {
                Query query1 = Query.query(Criteria.where("label").is(label));
                Update update1 = Update.update("count", res.getCount() + 1);
                mongoTemplate.updateFirst(query1, update1, Label.class,  "label");
            }
        }
    }

    @Override
    public void CheckAndReject(String articleId) {
        Query query = Query.query(Criteria.where("articleId").is(articleId));
        Update update = Update.update("flag", -1);
        mongoTemplate.updateFirst(query, update, Article.class, "article");
    }

    @Override
    public List<Article> selectArticleByLabel(Article article) {
        List<String> labels = article.getLabels();
        List<Article> list = new ArrayList<>();
        Pattern pattern;
        for (String label : labels) {
            pattern = Pattern.compile("^#.*"+ label.split("#")[0] + ".*$", Pattern.CASE_INSENSITIVE);
            Query query = new Query().addCriteria(Criteria.where("labels").regex(pattern));
            List<Article> temp = mongoTemplate.find(query, Article.class, "article");
            for (Article a : temp) {
                if (!list.contains(a)) {
                    list.add(a);
                }
            }
        }
        list.sort(Comparator.comparingInt(Article::getVisit).reversed());
        return list;
    }

    @Override
    public void commitComment(CommitCommentParams commentParams) {
        Query query = Query.query(Criteria.where("articleId").is(commentParams.getArticleId()));
        List<Reply> list = new ArrayList<>();
        Update update = new Update();
        Comment comment = new Comment();
        comment.setCommentId(commentParams.getPhone() + new TimeStamp().getTimeStamp());
        comment.setDate(new Date());
        comment.setUserName(commentParams.getUserName());
        comment.setPhone(commentParams.getPhone());
        comment.setText(commentParams.getText());
        comment.setAvatar(commentParams.getAvatar());
        comment.setReplies(list);
        update.addToSet("comments", comment);
        mongoTemplate.upsert(query, update, Article.class, "article");
    }

    @Override
    public void deleteMyComment(DeleteCommentParams deleteCommentParams) {
        Article article = articleRepository.findByArticleId(deleteCommentParams.getArticleId());
        assert article != null;
        List<Comment> comments = article.getComments();
        Comment comment = null;
        for (Comment c : comments) {
            if (c.getCommentId().equals(deleteCommentParams.getCommentId()) && c.getPhone().equals(deleteCommentParams.getPhone())) {
                comment = c;
                break;
            }
        }
        Query query1 = Query.query(Criteria.where("articleId").is(deleteCommentParams.getArticleId()));
        Update update = new Update();
        update.pull("comments", comment);
        mongoTemplate.updateFirst(query1, update, Article.class, "article");
    }

    @Override
    public void clickLike(ClickLikeParams clickLikeParams) {
        UserInfo userInfo = new UserInfo();
        userInfo.setPhone(clickLikeParams.getPhone());
        userInfo.setUserName(clickLikeParams.getUserName());
        Query query = Query.query(Criteria.where("articleId").is(clickLikeParams.getArticleId()));
        Update update = new Update();
        update.addToSet("likes", userInfo);
        mongoTemplate.upsert(query, update, Article.class, "article");
    }

    @Override
    public void clickUnlike(ClickLikeParams clickLikeParams) {
        Query query = Query.query(Criteria.where("articleId").is(clickLikeParams.getArticleId()));
        Update update = new Update();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserName(clickLikeParams.getUserName());
        userInfo.setPhone(clickLikeParams.getPhone());
        update.pull("likes", userInfo);
        mongoTemplate.updateFirst(query, update, Article.class, "article");
    }

    @Override
    public Article selectOneByArticleId(Article article) {
        Article res = articleRepository.findByArticleId(article.getArticleId());
        if(res == null) {
            return null;
        }
        else {
            articleRepository.removeByArticleId(article.getArticleId());
            res.setVisit(res.getVisit() + 1);
            articleRepository.save(res);
            return articleRepository.findByArticleId(res.getArticleId());
        }
    }

    @Override
    public List<Article> getArticlesByType(String type) {
        List<Article> list = articleRepository.findAllByClassIdAndFlag(type, 1);
        if (list.size() == 0) {
            list = articleRepository.findAllByClasstwoIdAndFlag(type,1);
        }
        return list;
    }

    @Override
    public List<Article> getArticlesByTitle(Article article) {
        String title = article.getTitle();
        Pattern pattern = Pattern.compile("^.*"+title + ".*$", Pattern.CASE_INSENSITIVE);
        Query query = new Query().addCriteria(Criteria.where("title").regex(pattern));
        List<Article> list = mongoTemplate.find(query, Article.class, "article");
        list.sort(Comparator.comparingInt(Article::getVisit).reversed());
        return list;
    }

    @Override
    public List<Article> getNotPassArticles() {
        List<Article> articles = articleRepository.findAllByFlag(0);
        return articles;
    }

    @Override
    public List<Article> getMyArticles(Article article) {
        String phone = article.getPhone();
        List<Article> list = articleRepository.findAllByPhone(phone);
        return list;
    }

    @Override
    public List<Article> getHotArticles() {
        List<Article> list = null;
        Query query = Query.query(Criteria.where("flag").is(1));
        Sort sort = Sort.by(Sort.Direction.DESC, "visit");
        query.with(sort);
        list = mongoTemplate.find(query, Article.class, "article");
        if (list.size() < 10) {
            return list;
        } else {
            return list.subList(0,10);
        }
    }

    @Override
    public void replyComment(ReplyCommentParams replyCommentParams) {
        String articleId = replyCommentParams.getArticleId();
        String commentId = replyCommentParams.getCommentId();
        Reply reply = new Reply();
        reply.setReplyId(replyCommentParams.getPhone() + new TimeStamp().getTimeStamp());
        reply.setUrls(replyCommentParams.getUrls());
        reply.setPhone(replyCommentParams.getPhone());
        reply.setDate(new Date());
        reply.setUserName(replyCommentParams.getUserName());
        reply.setText(replyCommentParams.getText());
        Query query = Query.query(Criteria.where("articleId").is(articleId).and("comments.commentId").is(commentId));
        Update update = new Update();
        update.addToSet("comments.$.replies", reply);
        mongoTemplate.updateFirst(query, update, Article.class, "article");
    }

    @Override
    public void deleteReply(DeleteReplyParams deleteReplyParams) {
        String articleId = deleteReplyParams.getArticleId();
        String commentId = deleteReplyParams.getCommentId();
        String replyId = deleteReplyParams.getReplyId();
        String phone = deleteReplyParams.getPhone();
        Article article = articleRepository.findByArticleId(articleId);
        Reply reply = null;
        assert article != null;
        List<Comment> comments = article.getComments();
        for (Comment c : comments) {
            if (c.getCommentId().equals(commentId)) {
                List<Reply> replies = c.getReplies();
                for (Reply r : replies) {
                    if (r.getReplyId().equals(replyId) && r.getPhone().equals(phone)) {
                        reply = r;
                        break;
                    }
                }
            }
        }
        Query query1 = Query.query(Criteria.where("articleId").is(articleId).and("comments.commentId").is(commentId));
        Update update = new Update();
        update.pull("comments.$.replies", reply);
        mongoTemplate.upsert(query1, update, Article.class, "article");
    }

    @Override
    public int deleteOnesAll(String phone) {
        int flag = articleRepository.removeByPhone(phone);
        return flag;
    }

    @Override
    public Integer getDayCount(String dateStr) {
        DateUtil dateUtil = new DateUtil();
        List<Article> list = articleRepository.findAllByFlag(1);
        List<Article> res = new ArrayList<>();
        for (Article article : list) {
            if (dateUtil.getStrByDate(article.getDate()).equals(dateStr)) {
                res.add(article);
            }
        }
        return res.size();
    }

    @Override
    public boolean isLike(CollectParam collectParam) {
        String articleId = collectParam.getArticleId();
        String phone = collectParam.getPhone();
        Article article = articleRepository.findByArticleId(articleId);
        if (article == null) {
            return false;
        } else {
            List<UserInfo> likes = article.getLikes();
            for (UserInfo user : likes) {
                if (user.getPhone().equals(phone)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public List<Article> getArticlesByComment() {
        List<Article> articles = articleRepository.findAllByFlag(1);
        Collections.sort(articles);
        if (articles.size() > 10) {
            return articles.subList(0,10);
        } else {
            return articles;
        }

    }
    @Override
    public List<Article> getBlogByPhone(String mobile) {
        System.out.println("getBlogByPhone:"+mobile);
        Query query=null;
        if(mobile.equals("1321512584@qq.com")){
            query= Query.query(Criteria.where("flag").is(1));
        }else{
            query= Query.query(Criteria.where("flag").is(1).and("phone").is(mobile));
        }
        List<Article> list = mongoTemplate.find(query, Article.class, "article");
        return list;
    }

    @Override
    public Integer selectTotalCount() {
        Query query = Query.query(Criteria.where("flag").is(1));
        List<Article> list = mongoTemplate.find(query, Article.class, "article");

        return list.size();
    }


    @Override
    public HashMap<String,Integer> selectHotLabels(){
        Aggregation aggregation1 = Aggregation.newAggregation(Aggregation.group("classId").count().as("value"), Aggregation.sort(Sort.Direction.DESC, "value"),Aggregation.limit(5));
        AggregationResults<BasicDBObject> outputTypeCount1 =
                mongoTemplate.aggregate(aggregation1, "article", BasicDBObject.class);


        HashMap<String,Integer> hashMap = new HashMap<>();
        for (Iterator<BasicDBObject> iterator = outputTypeCount1.iterator(); iterator.hasNext(); ) {
            BasicDBObject obj = iterator.next();
            String key = obj.get("_id").toString();
            Integer num = Integer.parseInt(obj.get("value").toString());
            System.out.println(key+"  "+num);
            hashMap.put(key,num);
        }
        return hashMap;
    }
}
